package com.wodan.zhongjinjicang.common.orm.command;

import java.lang.reflect.Method;
import java.util.Map;

import com.wodan.zhongjinjicang.common.orm.command.base.AbstractSqlCommandExecutor;
import com.wodan.zhongjinjicang.common.orm.command.read.SqlQueryAllExecutor;
import com.wodan.zhongjinjicang.common.orm.command.read.SqlQueryByIdExecutor;
import com.wodan.zhongjinjicang.common.orm.command.read.SqlQueryByIdsExecutor;
import com.wodan.zhongjinjicang.common.orm.command.write.*;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.util.Assert;

import com.google.common.collect.Maps;


/**
 * 
 * @ClassName: SqlCommandExecutorRegistry
 * @author Administrator
 * @date 2015-11-5 下午4:51:43
 * @history
 * 
 */
public class SqlCommandExecutorRegistry implements InitializingBean {
	private static final TypeHandlerRegistry TYPE_HANDLER_REGISTRY = new TypeHandlerRegistry();
	
	private Map<Method, SqlCommandExecutor> METHOD_EXECUTOR_MAP = Maps.newHashMap();

	private Map<SqlCommandType, SqlCommandExecutor> SQL_COMMAND_EXECUTOR_MAP = Maps.newHashMap();

	private JdbcTemplate jdbcTemplate;
	
	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}
	
	@Override
	public void afterPropertiesSet() throws Exception {
		registMethodExecutor(new SqlInsertExecutor());
		registMethodExecutor(new SqlUpdateByIdExecutor());
		registMethodExecutor(new SqlBatchInsertExecutor());
		registMethodExecutor(new SqlBatchDeleteExecutor());
		registMethodExecutor(new SqlQueryByIdExecutor());
		registMethodExecutor(new SqlQueryByIdsExecutor());
		registMethodExecutor(new SqlQueryAllExecutor());
		registMethodExecutor(new SqlDeleteByIdExecutor());

		registSqlTypeExecutor(new SqlUpdateCommonExecutor());
	}

	private void registSqlTypeExecutor(AbstractSqlCommandExecutor executor) {
		injectAttributes(executor);
		
		SqlCommandType sqlCommandType = executor.getSqlCommandType();
		if (SQL_COMMAND_EXECUTOR_MAP.containsKey(sqlCommandType)) {
			throw new IllegalStateException("SqlCommandType[" + sqlCommandType + "] is registed");
		}

		SQL_COMMAND_EXECUTOR_MAP.put(sqlCommandType, executor);
	}

	private void injectAttributes(AbstractSqlCommandExecutor executor) {
		executor.setJdbcTemplate(jdbcTemplate);
		executor.setTypeHandlerRegistry(TYPE_HANDLER_REGISTRY);
	}

	private void registMethodExecutor(AbstractSqlCommandExecutor executor) {
		injectAttributes(executor);
		
		Method proxyMethod = executor.getProxyMethod();
		if (METHOD_EXECUTOR_MAP.containsKey(proxyMethod)) {
			throw new IllegalStateException("proxyMethod[" + proxyMethod + "] is registed");
		}
		METHOD_EXECUTOR_MAP.put(proxyMethod, executor);
	}

	/**
	 * 根据方法得到sql命令的执行方法
	 * 
	 * @Description:
	 * @param method
	 * @return
	 */
	public SqlCommandExecutor getByMethod(Method method) {
		Assert.notNull(method);

		return METHOD_EXECUTOR_MAP.get(method);
	}

	public SqlCommandExecutor getBySqlType(SqlCommandType sqlCommandType) {
		Assert.notNull(sqlCommandType);

		return SQL_COMMAND_EXECUTOR_MAP.get(sqlCommandType);
	}
}
